package drds.plus.executor.command_handler.query.join;

import drds.plus.executor.ExecuteContext;
import drds.plus.executor.command_handler.query.AbstractQueryHandler;
import drds.plus.executor.cursor.cursor.ISortingCursor;
import drds.plus.executor.data_node_executor.DataNodeExecutorContext;
import drds.plus.executor.repository.Repository;
import drds.plus.sql_process.abstract_syntax_tree.execute_plan.ExecutePlan;
import drds.plus.sql_process.abstract_syntax_tree.execute_plan.query.Join;
import drds.plus.sql_process.abstract_syntax_tree.execute_plan.query.Query;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;

import java.util.ArrayList;
import java.util.List;

@Slf4j
public class IndexNestedLoopJoinHandler extends AbstractQueryHandler {
    public Logger log() {
        return log;
    }

    public IndexNestedLoopJoinHandler() {
        super();
    }


    protected ISortingCursor doQuery(ExecuteContext executeContext, ExecutePlan executePlan, ISortingCursor cursor) throws RuntimeException {
        return doIndexNestLoop(executeContext, executePlan, cursor);
    }

    protected ISortingCursor doIndexNestLoop(ExecuteContext executeContext, ExecutePlan executePlan, ISortingCursor cursor) throws RuntimeException {
        Repository repository = executeContext.getRepository();
        // 默认右节点是有索引的。
        Join join = (Join) executePlan;
        Query leftNode = join.getLeftNode();
        ISortingCursor leftSideCursor = null;
        ISortingCursor rightSideCursor = null;
        try {
            leftSideCursor = DataNodeExecutorContext.getExecutorContext().getDataNodeExecutor().execute(executeContext, leftNode);
            /**
             * 右边调的是mget，所以不需要在创建的时候初始化
             */
            join.getRightNode().setLazyLoad(true);
            rightSideCursor = DataNodeExecutorContext.getExecutorContext().getDataNodeExecutor().execute(executeContext, join.getRightNode());
        } catch (RuntimeException e) {
            List<RuntimeException> exs = new ArrayList();
            if (leftSideCursor != null) {
                exs = leftSideCursor.close(exs);
            }
            if (rightSideCursor != null) {
                exs = rightSideCursor.close(exs);
            }
            if (!exs.isEmpty()) {
                throw exs.get(0);
            } else {
                throw e;
            }
        }

        cursor = repository.getCursorFactory().indexNestLoopCursor(executeContext, (Join) executePlan, leftSideCursor, join.getLeftJoinColumnList(), rightSideCursor, join.getRightJoinColumnList());
        return cursor;
    }
}
